import os
from datetime import datetime
import random
from typing import Dict, Optional, List
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
import warnings
import matplotlib.patches as mpatches

from ChipSchduile.entry.Machine import Machine

K = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
R = [1,2,3]

# 机器映射
machine_map = {
    1: "PM1", 2: "PM2", 3: "PM3", 4: "PM4", 5: "PM5", 6: "PM6", 7: "PM7", 8: "PM8", 9: "PM9", 10: "PM10",
    11: "LLA", 12: "LLB", 13: "LLC", 14: "LLD",
    15: "AL"
}

# 机械手映射（与你提供的 TM_map 对应）
TM_map = {1: "TM1", 2: "TM2", 3: "TM3"}


def show_gatt(
        result: Dict,
        machine_map: Optional[Dict] = machine_map,
        TM_map: Optional[Dict] = TM_map
):
    """完全动态适配版甘特图：使用全局资源映射，确保同一工件颜色一致"""
    # 忽略警告
    warnings.filterwarnings("ignore", message="Blended transforms not yet supported.")

    # 中文支持
    plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
    plt.rcParams["axes.unicode_minus"] = False

    moves = []
    # 遍历所有工序
    for j in result['SO'].keys():
        # 加工任务
        moves.append({
            "ModuleName": machine_map[result["phi"][j]],
            "StartTime": result["SO"][j],
            "EndTime": result["SO"][j] + result["Pt"][j],
            "MatId": result["job_id"][j]
        })

        # 运输任务
        moves.append({
            "ModuleName": TM_map[result["mu"][j]],
            "StartTime": result["ST"][j],
            "EndTime": result["ST"][j] + result["Tt"][j],
            "MatId": result["job_id"][j]
        })

    # 生成随机颜色映射，用于工件ID
    def generate_color():
        return f'#{random.randint(0, 0xFFFFFF):06x}'  # 生成一个随机的颜色

    # 为每个工件生成一个颜色映射
    matid_colors = {}
    for move in moves:
        matid = move["MatId"]
        if matid not in matid_colors:
            matid_colors[matid] = generate_color()

    print("=========创建画布=====================")
    plt.figure(figsize=(20, 10))

    # 设置横轴范围
    max_time = max([move["EndTime"] for move in moves])
    min_time = min([move["StartTime"] for move in moves])

    # 绘制每个工序
    for move in moves:
        module = move["ModuleName"]
        duration = move["EndTime"] - move["StartTime"]
        matid = move["MatId"]

        # 为工件ID选择颜色
        color = matid_colors.get(matid)  # 默认颜色是灰色

        # 绘制条形
        plt.barh(move["ModuleName"],
                 duration,
                 left=move["StartTime"],
                 height=0.3,
                 color=color,
                 )

    # 坐标轴设置
    plt.yticks(range(len(machine_map)), machine_map)  # y轴刻度位置
    plt.xlabel('Time (seconds)')
    plt.ylabel('Modules')
    plt.title('gatt_fig')

    # 添加图例
    legend_patches = [
        mpatches.Patch(color=color, label=f'MatID {matid}')
        for matid, color in matid_colors.items()
    ]

    # 将图例添加到图表中
    plt.legend(handles=legend_patches, bbox_to_anchor=(0.5, -0.15), loc='upper center', ncol=10)

    # 调整布局
    plt.grid(axis='x', alpha=0.5)
    plt.tight_layout(pad=1.0)  # 调整间距

    # 保存图像
    # 获取当前时间戳
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")

    # 确保figure文件夹存在
    if not os.path.exists('figure'):
        os.makedirs('figure')  # 如果文件夹不存在则创建

    # 保存图片到figure文件夹下
    plt.savefig(f'figure/gantt_{timestamp}.png', dpi=300, bbox_inches='tight')
    plt.close()  # 关闭图形，避免内存占用


def print_schedule_results(result):
    """
    打印模型求解结果，即使未找到最优解也会尝试打印可行解
    :param result: 求解结果字典，可能包含状态码、可行解等信息
    :return:
    """
    # 检查结果是否有效
    if result is None:
        print("无求解结果数据")
        return

    # 提取状态码
    status = result.get("status", None)
    has_feasible_solution = all(key in result for key in ['SO', 'ST', 'Tt', 'Pt', 'mu', 'phi'])

    # 打印整体信息
    print("=" * 80)
    if status is None:
        print(f"{'半导体生产调度优化结果（最优解）':^80}")
    else:
        # 状态码说明（以Gurobi为例，可根据实际求解器调整）
        status_info = {
            9: "达到时间限制，已找到可行解",
            10: "最优解被证明不可行",
            11: "无可行解",
            12: "求解被中断"
        }.get(status, f"状态码: {status}")
        print(f"{'半导体生产调度优化结果（' + status_info + '）':^80}")
    print("=" * 80)

    # 打印基础指标
    if 'solve_time' in result:
        print(f"模型求解时间: {result['solve_time']:.4f} 秒")
    if 'Cmax' in result:
        print(f"最大完工时间(Cmax): {result['Cmax']:.2f} 秒")
    print("-" * 80 + "\n")

    # 打印工序时间表
    if has_feasible_solution:
        print(f"{'工序时间表（含工件ID）':^100}")
        print("-" * 100)
        # 表头（新增“工件ID”列）
        print(f"{'工件ID':<8} | {'工序编号':<8} | {'运输任务':^36} | {'加工任务':^36}")
        print(
            f"{'':<8} | {'':<8} | {'开始时间':<10} {'执行时间':<10} {'机械手':<10} | {'开始时间':<10} {'执行时间':<10} {'机器':<10}")
        print("-" * 100)

        # 按工序编号排序输出
        for j in sorted(result['SO'].keys()):
            job_id = result['job_id'][j]  # 从映射中获取工件ID
            # 运输任务信息
            st_time = f"{result['ST'][j]:.2f}"
            tt_time = f"{result['Tt'][j]:.2f}"
            transport_robot = result['mu'][j]
            # 加工任务信息
            so_time = f"{result['SO'][j]:.2f}"
            pt_time = f"{result['Pt'][j]:.2f}"
            process_machine = result['phi'][j]

            # 格式化输出（含工件ID）
            print(
                f"{job_id:<8} | {j:<8} | {st_time:<10} {tt_time:<10} {transport_robot:<10} | {so_time:<10} {pt_time:<10} {process_machine:<10}")

        print("\n" + "-" * 80)

        # 打印资源分配汇总
        print(f"{'资源分配汇总':^80}")
        print("-" * 80)
        print("机器分配情况:")
        for machine in sorted(set(result['phi'].values())):
            processes = [j for j, m in result['phi'].items() if m == machine]
            print(f"  机器 {machine}: 负责工序 {processes}")

        print("\n机械手分配情况:")
        for robot in sorted(set(result['mu'].values())):
            transports = [j for j, r in result['mu'].items() if r == robot]
            print(f"  机械手 {robot}: 负责工序 {transports}")

        print("\n" + "=" * 80)
        # 绘制甘特图逻辑，有可行解时调用绘图函数
        print("===============开始绘制甘特图========================")

        fig = show_gatt(result, machine_map,TM_map)
        plt.show()  # 显示甘特图图表


    else:
        # 无可行解时的提示（区分“解析错误”和“真无可行解”）
        if "error" in result:
            print(f"找到可行解，但解析失败：{result['error']}")
        else:
            print("未找到任何可行解，无法展示工序和资源分配详情，也无法绘制甘特图")
        if status is not None:
            print(f"状态码 {status} 说明: {status_info}")  # 复用之前定义的状态说明
        print("\n" + "=" * 80)


